/*
    Copyright (c) 2011 Marcus Schwartz.  All rights reserved.
 
    This file is part of NetObjects-Arduino.

    NetObjects-Arduino is free software: you can redistribute it and/or 
    modify it under the terms of the GNU Lesser General Public License as 
    published by the Free Software Foundation, either version 3 of the 
    License, or (at your option) any later version.

    NetObjects-Arduino is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public 
    License along with NetObjects-Arduino.  If not, see 
    <http://www.gnu.org/licenses/>.
 */

#ifndef __NetObjects_h
#define __NetObjects_h

#include "WProgram.h"
#include <XBee.h>

#define MOTION_STOP     (0 << 4)
#define MOTION_FWD      (1 << 4)
#define MOTION_REV      (2 << 4)

#define ANGLE_STRAIGHT  (0 << 2)
#define ANGLE_LEFT      (1 << 2)
#define ANGLE_RIGHT     (2 << 2)

#define BUTTON_C        (1 << 1)
#define BUTTON_Z        (1 << 0)

#define MOTION_DEBUG_MESSAGE        1
#define MOTION_SKID_STEER_VEHICLE   2
#define MOTION_TWO_BUTTON_JOYSTICK  3

class NetObjectsControl;
class DebugMessage;
class SkidSteerVehicle;
class TwoButtonJoystick;

class NetObjectsUpdate {
    public:
        NetObjectsUpdate(NetObjectsControl *);
        uint8_t type(void);
        SkidSteerVehicle skidSteerVehicle(void);
        DebugMessage debugMessage(void);
        TwoButtonJoystick twoButtonJoystick(void);
        void setData(byte *);
    private:
        uint8_t _type;
        void *_data;
        NetObjectsControl *_motion;
};

class NetObject {
    public:
        NetObject();
        uint8_t ptype;
        NetObjectsControl * _motion;
        uint8_t skip_count;
};

struct motion_vector {
    uint8_t magnitude;
    uint8_t angle;
    uint8_t flags;
};

struct motion_status {
    int speed_l;
    int speed_r;
    int heading;
    uint8_t rssi;
};

class TwoButtonJoystick : public NetObject {
    public:
        TwoButtonJoystick(void);
        TwoButtonJoystick(NetObjectsControl *);
        TwoButtonJoystick(NetObjectsControl *, void *);
        void updateFromXY(int x, int y, int brake, int accel);

        int packetBytes(void);
        void *packetData(void);
        void broadcast(void);

        uint8_t magnitude(void);
        uint8_t angle(void);
        uint8_t flags(void);

    private:
        struct motion_vector vec;
        struct motion_vector last_vec;
};

class SkidSteerVehicle : public NetObject {
    public:
        SkidSteerVehicle(void);
        SkidSteerVehicle(NetObjectsControl *);
        SkidSteerVehicle(NetObjectsControl *, void *);

        void broadcast(void);
        int packetBytes(void);
        void *packetData(void);
        void updateFromTwoButtonJoystick(TwoButtonJoystick);
        void updateFromVector(uint8_t, uint8_t, uint8_t);

        void maxSpeed(uint8_t);
        void heading(int);
        int heading(void);
        void rssi(uint8_t);
        uint8_t rssi(void);
        void speed_l(int);
        int speed_l(void);
        void speed_r(int);
        int speed_r(void);
    private:
        struct motion_status stat;
        struct motion_status last_stat;
        uint8_t _max_speed;
};

class DebugMessage : public NetObject {
    public:
        DebugMessage(NetObjectsControl *, char *);
        DebugMessage(NetObjectsControl *, void *);
        uint8_t length;
        char text[40];
        int packetBytes(void);
        void *packetData(void);
        void broadcast(void);
};

class NetObjectsControl {
    public:
        NetObjectsControl();
        void begin(int speed);
        NetObjectsUpdate getUpdate();
        void *getPacket(void);
        void debug(char *text);
        void broadcast(TwoButtonJoystick *);
        void broadcast(DebugMessage *);
        void broadcast(SkidSteerVehicle *);
        void sendPacket(void *, int, uint8_t);
        void processUpdate(DebugMessage);
        char * getDebug(void);
        int getRssi(void);
        void localDebug(int l);

    private:
        char _debug[40];
        XBee _xbee;
        Tx16Request _tx;
        TxStatusResponse _txStatus;
        XBeeResponse _response;
        Rx16Response _rx;
        int _localDebug;
        int _loop;
        int _rssi;
};

#endif
